02: Clustering of product catalogs with Agglomerative Clustering and t-SNE

Contents

02: Clustering of product catalogs with Agglomerative Clustering and t-SNE#

In this notebook, we will introduce our first approach product clustering using hierarchical clustering of catalogs and size titles as labels. This notebook will discuss:

  • Problem statement and relevance

  • Definition and Formulation of Agglomerative Clustering

  • Flattening of hierarchical clusters and visualization

  • Comparison of t-SNE (manifold learning) and PCA (dimensionality reduction) for data visualization in lower dimensional space

  • Analysis of the results

Keywords: Agglomerative Clustering, Hierarchical Clustering, t-SNE, Vinted

Table of contents

Introduction#

Image Description

The problem we aim to solve here is to cluster product catalogs into higher levels of catalogs. By nature, Vinted already has an hierarchical sequence of natural catalogs. For instance, the primary labels are: Woman, Men, Children, House, Animals, Others

  • Woman -> Bras, dresses, leggings, pantyhoses, as well as common clothes (trousers, shirts, shoes, etc)

  • Men -> Shoes, shorts, t shirts, shirts, etc

  • Children -> same as above

  • House -> blankets, towels, pillows, decoration, etc

  • Animals -> Toys, grooming, training, etc

  • Entertainment -> …

In addition, this hierarchies have 4 to 5 layers of depth.

  • Men -> Shoes -> Sneakers -> Sports sneakers

  • Men -> Clothing -> T shirts and tops -> T shirts -> Simple T shirts

Product catalogs and title sizes#

After skimming through the data, I realized the best segmentation feature here is the title sizes. Each category is often linked to a specific size title. Sometimes its very obvious (shoes vs clothing), specially in higher level segmentation; sometimes it can be trickier (women shoes vs men shoes).

As an example:

  • M, XL, S, etc which are the standard clothing sizes

    • But sizes differ between men and women

  • no_size for the products which do not have size labels

    • Impossible to distinguish no_size title based on sizing alone

  • numeric sizes (40, 41) which refers to footwear

  • kids sizes (8 anos, 12 anos, etc)

  • cup sizes (95D, 80B)

  • jewelry (which im assuming 30 mm diameter refers to)

  • volume units (40 x 45 cm)

  • weight units (9-18kgs)

  • jeans sizes (waist measurements W33)

    • But sizes differ between men and women

Preprocessing#

Loading the data and required packages#

# importing base packages
import pandas as pd
from sqlalchemy import create_engine
import os
import json
import numpy as np

# clustering packages
from sklearn.preprocessing import MinMaxScaler
from scipy.cluster.hierarchy import linkage, fcluster, dendrogram
import numpy as np

# visualization
import matplotlib.pyplot as plt
import plotly.graph_objects as go
#import plotly.figure_factory as ff
import plotly.express as px
from sklearn.manifold import TSNE

from sklearn.decomposition import TruncatedSVD
import pandas as pd
def load_credentials(path = "aws_rds_credentials.json"):
     with open(path, 'r') as file:
          config = json.load(file)

     # set up credentials
     for key in config.keys():
          os.environ[key] = config[key]

     return

time_interval = 90 #days

load_credentials()

aws_rds_url = f"postgresql://{os.environ['user']}:{os.environ['password']}@{os.environ['host']}:{os.environ['port']}/{os.environ['database']}?sslmode=require"

engine = create_engine(aws_rds_url)
sql_query = f"""SELECT brand_title, price_numeric, catalog_id, size_title
               FROM public.tracking_staging 
               WHERE date >= CURRENT_DATE - INTERVAL '{time_interval} days'
               LIMIT 500000
               """
data = pd.read_sql(sql_query, engine)
data.head(5)
brand_title price_numeric catalog_id size_title
0 Local 18 200 M / 38 / 10
1 Local 18 200 M / 38 / 10
2 Local 8 222 S / 36 / 8
3 Local 16 2927 M / 38 / 10
4 Bershka 28 532 S / 36 / 8

The Dataset#

The dataset used is the Vinted dataset. For this purpose, we are selecting only these variables.

Variable

Description

Range/Unit

brand_title

Brand

Char (category)

price_numeric

Base price

Numeric

catalog_id

Catalog

Numeric (category)

size_title

Size

Char (category)

data.isna().sum()
brand_title      0
price_numeric    0
catalog_id       0
size_title       0
dtype: int64
data[["brand_title", "size_title"]].nunique()
brand_title    8018
size_title      292
dtype: int64

Data preparation#

Before we start, we need to clean and reshape the data to a preferred format. For this purpose we are using only the sizes as clustering dimensions, because we understand different sizing plays a huge role in product catalogs and reflects other latent variables such as gender, age and type.

The most reasonable metric here is count of each product per size title since price is subjective and affected by other factors. If we were to chose median price or volume, it could be more easily affected by exegenous variables.

data.dropna(axis = 0, inplace= True)
data
brand_title price_numeric catalog_id size_title
0 Local 18 200 M / 38 / 10
1 Local 18 200 M / 38 / 10
2 Local 8 222 S / 36 / 8
3 Local 16 2927 M / 38 / 10
4 Bershka 28 532 S / 36 / 8
... ... ... ... ...
499995 2 2339
499996 2 2492
499997 Lilou Secret 1 223 M / 38 / 10
499998 1 123 L / 40 / 12
499999 3 1079 S / 36 / 8

500000 rows × 4 columns

# using product count as metric
pivot_size = data.pivot_table(values='price_numeric', columns='size_title', index='catalog_id', aggfunc='count')
pivot_size.head(5)
size_title 0-13 kg 0-3 meses, 30 cm 1-2 anos, 49 cm 1-3 meses / 56 cm 10 10 anos / 140 cm 100 cm 100 x 150 cm 100B 100E 105 cm 11 anos / 146 cm 11-25 kg 110 cm 115 cm 12 anos / 152 cm 12 ou mais > 56 cm 12-18 meses / 80 cm 120 cm 120 x 160 cm 125 cm 125 x 150 cm 13 anos / 158 cm 13-15 130 x 170 cm 14 anos / 164 cm 14,1 mm Ø / 4 14,9 mm Ø / 6,5 15 anos / 170 cm 15 ou inferior 15,3 mm Ø / 8 15,7 mm Ø / 9,5 15-36 kg 150 cm - 199 cm 16 16 anos / 176 cm 16,1 mm Ø / 10,5 16,5 mm Ø / 12 16,9 mm Ø / 13,5 16-18 17 17,3 mm Ø / 14,5 17,7 mm Ø / 16 18 18,1 mm Ø / 18,5 18,5 mm Ø / 19,5 18-24 meses / 86 cm 19 19 mm Ø / 21 19,4 mm Ø / 22,5 19,8 mm Ø / 23,5 19-21 2-3 anos, 51 cm 20 20,2 mm Ø / 25 20,6 mm Ø / 26 200 cm - 249 cm 21 21 mm Ø / 27 22 22,2 mm Ø / 31 22,6 mm Ø / 32 22-36 kg 23 24 24-36 meses / 92 cm 25 25-27 250 cm - 299 cm 26 27 28 28-30 29 2XL 3 anos / 98 cm 3-5 anos, 53 cm 3-6 meses / 62 cm 3-6 meses, 42 cm 30 30 mm ou menos 30 x 50 cm 300 cm ou mais 31 31 mm - 38 mm 31-33 32 33 34 34-36 35 35 x 50 cm 35.5 36 36.5 37 37 cm 37-39 37.5 38 38 cm 38,5 38.5 39 39 - 42 mm 39 cm 39,5 39.5 ... 70 x 90 cm 70A e AA 70B 70C 70D 75 cm 75A e AA 75B 75C 75D 75E 7XL 7XL / 54 / 26 8 8 anos / 128 cm 8,5 8-12 anos, 56 cm 80 cm 80B 80C 80D 80E 85 cm 85B 85C 85D 8XL / 56 / 28 9 9 anos / 134 cm 9,5 9-12 meses / 74 cm 9-18 kg 9-20 kg 90 cm 90C 90D 90E 95 cm 95C 95D 95E 9XL / 58 / 30 A partir de 0 meses A partir de 3 meses Ajustável Até 1 mês / 50 cm Até 149 cm Berço/Alcofa Berço/Cama de bebé Casal (155-190 cm x 200-220 cm) Casal King (180–200 cm x 200 cm) Casal King (220-240 cm x 220-260 cm) Casal Queen (150–180 cm x 190–200 cm) Casal Queen (200 cm x 200-220 cm) L L / 40 / 12 L | 47-52 M M / 38 / 10 M | 39-42 M | 43-46 Mini berço Outro Outros PT 32 | W23 PT 34 | W24 PT 34 | W25 PT 36 | W26 PT 36 | W27 PT 38 | W28 PT 38 | W29 PT 40 | W30 PT 40 | W31 PT 42 | W32 PT 42 | W33 PT 44 | W34 PT 44 | W35 PT 46 | W36 PT 48 | W38 PT 50 | W40 PT 52 | W42 PT 54 | W44 PT 56 | W46 PT 58 | W48 PT 60 | W50 PT 62 | W52 PT 64 | W54 Prematuro, até 44 cm Prematuros, 30 cm Qualquer Recém-nascidos, 44 cm S S / 36 / 8 S | 35-38 S | 38-42 Solteiro (135-150 cm x 200-220 cm) Tamanho único XL XL / 42 / 14 XS XS / 34 / 6 XS | 36-37 XXL XXL / 44 / 16 XXS XXS / 32 / 4 XXXL XXXL / 46 / 18 XXXS / 30 / 2
catalog_id
11 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 215.0 NaN NaN 402.0 NaN NaN NaN 48.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 456.0 NaN NaN NaN 33.0 NaN 93.0 NaN 326.0 NaN NaN 60.0 NaN 19.0 NaN 52.0 29.0
14 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 264.0 NaN NaN 322.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 368.0 NaN NaN NaN NaN NaN 110.0 NaN 254.0 NaN NaN 39.0 NaN 4.0 NaN 5.0 NaN
16 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 1.0 NaN NaN 21.0 NaN 49.0 NaN NaN NaN 84.0 NaN NaN 22.0 114.0 NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
18 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 2.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 317.0 NaN NaN 770.0 NaN NaN NaN 42.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 792.0 NaN NaN NaN 238.0 NaN 225.0 NaN 161.0 NaN NaN 47.0 NaN 9.0 NaN 4.0 1.0
19 349.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

5 rows × 292 columns

# for each catalog, we are going to use minmaxscalar to standardize the scale of the data

pivot_combined = pivot_size.fillna(0)
pivot_combined = pivot_combined.T
for col in pivot_combined.columns:
    pivot_combined[col] = MinMaxScaler().fit_transform(X = pivot_combined[[col]]) #/pivot_combined[col].sum()
pivot_combined 
catalog_id 11 14 16 18 19 20 22 26 83 84 86 87 88 89 90 91 92 94 96 97 98 99 119 120 123 124 140 141 143 145 152 153 156 157 158 159 160 161 162 163 164 165 166 167 176 178 179 184 185 187 189 190 191 192 193 194 195 196 197 198 199 200 203 204 205 211 213 215 218 219 220 221 222 223 224 225 227 228 229 230 231 234 241 242 243 244 246 247 248 259 260 261 263 264 265 266 267 268 271 272 287 288 525 526 529 532 534 538 543 ... 2655 2656 2657 2659 2661 2662 2663 2664 2672 2673 2674 2676 2677 2678 2680 2681 2682 2683 2684 2685 2686 2690 2692 2695 2696 2697 2698 2701 2702 2704 2705 2707 2708 2709 2710 2711 2713 2714 2715 2717 2718 2719 2720 2721 2722 2726 2727 2728 2729 2730 2732 2733 2734 2735 2738 2742 2744 2745 2746 2749 2750 2751 2752 2753 2911 2912 2913 2914 2917 2918 2920 2921 2922 2923 2924 2925 2927 2928 2929 2931 2932 2933 2934 2937 2938 2939 2940 2941 2942 2944 2945 2949 2950 2951 2952 2953 2954 2955 2956 2958 2959 2960 2961 2964 2965 2967 2968 2969 2970
size_title
0.000000 0.000000 0.0 0.000000 1.0 0.622549 0.223577 1.0 0.000000 0.0 0.211268 1.0 0.869565 1.0 0.089286 0.0 0.000000 1.0 0.115385 0.593074 1.0 1.0 0.0 0.000000 0.000000 0.000000 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000 0.000000 0.0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 0.0 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.0 0.000000 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.0 0.161677 0.138158 0.0 1.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0000 0.000000 0.000000 0.000000 0.000000 0.000 0.000000 0.0 0.032802 0.032258 0.00000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.000000 0.000000 0.0 1.0 1.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0
0-13 kg 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000 0.000000 0.0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 0.0 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.0 0.000000 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0000 0.000000 0.000000 0.000000 0.000000 0.000 0.000000 0.0 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0-3 meses, 30 cm 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000 0.000000 0.0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 0.0 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.0 0.000000 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0000 0.000000 0.000000 0.000000 0.000000 0.000 0.000000 0.0 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1-2 anos, 49 cm 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000 0.000000 0.0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 0.0 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.0 0.000000 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0000 0.000000 0.000000 0.000000 0.000000 0.000 0.000000 0.0 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1-3 meses / 56 cm 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000 0.000000 0.0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 0.0 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.0 0.000000 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0000 0.000000 0.000000 0.000000 0.000000 0.000 0.000000 0.0 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
XXS 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000 0.000000 0.0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 0.0 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.0 0.000000 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0000 0.000000 0.000000 0.000000 0.000000 0.000 0.000000 0.0 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
XXS / 32 / 4 0.041667 0.010870 0.0 0.011364 0.0 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.000000 0.007440 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.042596 0.000000 0.000000 0.150376 0.115619 0.210682 0.114583 0.01125 0.039216 0.0000 0.003584 0.000000 0.000000 0.044794 0.031768 0.044271 0.000000 0.000000 0.0 0.0 0.159170 0.0 0.0 0.0 0.000000 0.000000 0.0 0.029520 0.000000 0.000000 0.00641 0.000000 0.000000 0.010753 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0000 0.000000 0.000000 0.000000 0.000000 0.000 0.000000 0.0 0.000000 0.000000 0.00000 0.000000 0.000735 0.000830 0.029233 0.066351 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.003012 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
XXXL 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.072165 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.409836 0.0 0.000000 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000 0.000000 0.0000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 0.0 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.0 0.000000 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0625 0.034314 0.097938 0.006116 0.015413 0.208 0.088235 0.0 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
XXXL / 46 / 18 0.114035 0.013587 0.0 0.005051 0.0 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.009346 0.005952 0.179688 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.044625 0.000000 0.007692 0.090226 0.040568 0.041543 0.002083 0.00375 0.012478 0.0025 0.000000 0.006772 0.007937 0.024213 0.051105 0.014757 0.056235 0.219626 0.0 0.0 0.083045 0.0 0.0 0.0 0.048193 0.072758 0.0 0.042448 0.055995 0.047619 0.00641 0.112128 0.127551 0.045400 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0000 0.000000 0.000000 0.000000 0.000000 0.000 0.000000 0.0 0.000000 0.000000 0.03856 0.088398 0.033064 0.068050 0.001827 0.075829 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.090361 0.793103 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
XXXS / 30 / 2 0.063596 0.000000 0.0 0.001263 0.0 0.000000 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.075512 0.000000 0.000000 0.024341 0.065282 0.000000 0.00000 0.000000 0.0000 0.000000 0.000000 0.000000 0.025424 0.000000 0.000000 0.000000 0.000000 0.0 0.0 0.000000 0.0 0.0 0.0 0.000000 0.000000 0.0 0.013790 0.000000 0.000000 0.00000 0.000000 0.000000 0.000000 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0000 0.000000 0.000000 0.000000 0.000000 0.000 0.000000 0.0 0.000000 0.000000 0.00000 0.000000 0.000000 0.007469 0.001218 0.000000 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.000000 0.000000 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0

292 rows × 852 columns

Agglomerative Hierarchical Clustering using Ward Linkage#

As indicated by the term hierarchical, the method seeks to build clusters based on hierarchy. Generally, there are two types of clustering strategies: Agglomerative and Divisive. Here, we mainly focus on the agglomerative approach, which can be easily pictured as a ‘bottom-up’ algorithm.

Ward Linkage Method#

There are four methods for combining clusters in agglomerative approach. The one we choose to use is called Ward’s Method. Unlike the others. Instead of measuring the distance directly, it analyzes the variance of clusters. Ward’s is said to be the most suitable method for quantitative variables.

\(\Delta(A,B) = \sum_{i\in A \bigcup B} ||\overrightarrow{x_i} - \overrightarrow{m}_{A \bigcup B}||^2 - \sum_{i \in A}||\overrightarrow{x_i} - \overrightarrow{m}_A||^2 -\sum_{i \in B}||\overrightarrow{x_i}- \overrightarrow{m}_B||^2 = \frac{n_An_B}{n_A+n_B} ||\overrightarrow{m}_A- \overrightarrow{m}_B||^2\)

where \(\overrightarrow{m}_j\) is the center of cluster j, and \(n_j\) is the number of points in it. Δ is called the merging cost of combining the clusters A and B. With hierarchical clustering, the sum of squares starts out at zero (because every point is in its own cluster) and then grows as we merge clusters. Ward’s method keeps this growth as small as possible.

The euclidean distance is the straight line distance between two points in Euclidean Space.

\(d(p,q) = \sqrt{(q_1 -p_1)^2 + (q_2 - p_2)^2 + \cdots + (q_n -p_n)^2} = \sqrt{\sum_{i=1} (q_i-p_i)^2}\)

# dist_matrix is long form distance matrix
# notice this is the intracluster SSE
def intracluster_sse(df: pd.DataFrame) -> float:
    avg = df.mean(axis = 1)
    sse = (df.T - avg).pow(2).sum().sum()
    return (sse)

linkage_matrix = linkage(pivot_combined.T, 'ward')
t_values = np.arange(1, 10.1, 0.1)
avg_sse = []
clusters = []
for t in t_values:
    res = fcluster(linkage_matrix, criterion = "distance", t = t)
    df = pd.DataFrame(res, index = pivot_combined.columns).reset_index()
    grouped_data = df.groupby(0)['catalog_id'].apply(list).reset_index()
    sse_list = []
    clusters.append(len(grouped_data))
    for catalog in grouped_data["catalog_id"]:
        sse_list.append(intracluster_sse(pivot_combined[catalog]))
    avg_sse.append(sum(sse_list))

fig = go.Figure()
fig.add_trace(go.Scatter(x=t_values, y=clusters, mode='lines+markers'))
fig.update_xaxes(title_text="Distance between cluster")
fig.update_yaxes(title_text="Number of clusters")
fig.update_layout(title="Elbow Method Chart - Clusters")
fig = go.Figure()
fig.add_trace(go.Scatter(x=t_values, y=avg_sse, mode='lines+markers'))
fig.update_xaxes(title_text="Distance between cluster")
fig.update_yaxes(title_text="Mean intra cluster SSE")
fig.update_layout(title="Elbow Method Chart - Mean SSE")

Dendrogram visualization#

Currently disabled because there are too many clusters.

X = dendrogram(linkage_matrix)
#fig = ff.create_dendrogram(np.array(X["icoord"]))
#fig.update_layout(width=800, height=500)
../_images/89ded2e86ca5926f0d1952ed92666b122f99b9053bd32962517fa985843c62f9.png
t = 2.5

res = fcluster(linkage_matrix, criterion = "distance", t = t)
df = pd.DataFrame(res, index = pivot_combined.columns).reset_index()

Analysis of Sizing Features#

In order to understand how to clustering was done, we are taking a look at each cluster top sizes as well as size dimension.

The result has 25 clusters and the max cluster has 135 labels.

grouped_data = df.groupby(0)['catalog_id'].apply(list).reset_index()
grouped_data['catalog_id_length'] = grouped_data['catalog_id'].apply(lambda x: len(x))
grouped_data.head(5)
0 catalog_id catalog_id_length
0 1 [19, 26, 87, 89, 94, 98, 99, 140, 141, 143, 14... 289
1 2 [1067, 1263, 1445, 1773, 1780] 5
2 3 [120, 124, 229, 1100, 1103, 1178, 1181, 1183, ... 10
3 4 [18, 123, 178, 179, 187, 191, 192, 193, 194, 1... 49
4 5 [198, 199, 200, 203, 204, 222, 227, 532, 574, ... 32

Visualizing the clusters#

t-Distributed Stochastic Neighbor Embedding (manifold embedding technique)#

t-Distributed Stochastic Neighbor Embedding (t-SNE) is a powerful dimensionality reduction technique used for visualizing high-dimensional data in lower-dimensional space. The main objectives of t-SNE are:

  • Preservation of local structure (locality) This means the points closer in high dimensional space should appear closer in a lower dimensional embedding.

  • Robustness to noise and outliers

  • Non linear embedding Self explanatory. It captures complex non linear relationships in the data, suitable for visualization of intricate manifolds.

  • Unsupervised learning

# Compute t-SNE embeddings
tsne = TSNE(n_components=2, random_state=42, perplexity=10)
X_tsne = tsne.fit_transform(pivot_combined.T)

pca_df = pd.DataFrame(data=X_tsne, 
                      columns=['PC1', 'PC2'], 
                      index = pivot_combined.T.index)

concat_df = pd.concat([pca_df, 
                       df.set_index("catalog_id")], 
                      ignore_index= False, 
                      axis=1)
concat_df = concat_df.rename(columns={0: 'Cluster'})
concat_df.index = concat_df.index.astype("str")

fig = px.scatter(concat_df, x='PC1', y='PC2', color='Cluster', title='t-SNE Plot')
fig

Visualizing the clustering on 2 dimensions using PCA#

PCA is a dimensionality reduction technique which can also be used to reduce the number of features in the dataset, while preserving its variance. PCA uses the covariance matrix and single value decomposition (SVD) to solve in order of the eigenvectors and eigen values of the covariance matrix. The eigen vectors represent the principal component (a new projection) and the eigenvalues the variance explained.

In this example, the variance explain by the 2 components is merely 30%, which means that there is a loss of 70% of the information.

pca = TruncatedSVD(n_components=2)

# Fit and transform the data
pca_result = pca.fit_transform(pivot_combined.T)

# Convert the result to a DataFrame
pca_df = pd.DataFrame(data=pca_result, columns=['PC1', 'PC2'], index = pivot_combined.T.index)
concat_df = pd.concat([pca_df, df.set_index("catalog_id")], ignore_index= False, axis=1)
concat_df = concat_df.rename(columns={0: 'Cluster'})
concat_df.head(5)
PC1 PC2 Cluster
catalog_id
11 0.013168 1.562881 6
14 0.012050 1.641709 6
16 0.000021 0.000171 30
18 0.016196 1.499577 4
19 0.999768 -0.009430 1
# Get the percentage variance explained by each principal component
explained_var_ratio = pca.explained_variance_ratio_

# Create a scatter plot with Plotly
fig = px.scatter(concat_df, x='PC1', y='PC2', color='Cluster', title='PCA Scatter Plot')
fig.update_layout(
    xaxis_title=f'PC1 ({explained_var_ratio[0]*100:.2f}% Variance Explained)',
    yaxis_title=f'PC2 ({explained_var_ratio[1]*100:.2f}% Variance Explained)'
)

Comparison of the methods#

PCA preserves the variance in the data, whereas t-SNE preserves the relationships between data points in a lower-dimensional space, making it quite a good algorithm for visualizing complex high-dimensional data. In short, t-SNE is my go to in visualization in lower dimensional space whereas PCA is more useful as a preprocessing step/dimensionality reduction algorithm.

Analysis of the results#

for catalog in grouped_data["catalog_id"]:
    top_10 = pivot_combined[catalog].sum(axis=1).sort_values(ascending=False).head(10)
    top_10 /= top_10.sum()
    
    # Create a bar chart
    fig = go.Figure([go.Bar(x=top_10.index, y=top_10.values)])
    fig.update_layout(title=f"Top 10 for Catalog {catalog}",
                      xaxis_title="Index",
                      yaxis_title="Sum",
                      )
    fig.show()